<template>
  <el-form
    :model="formData"
    :rules="rules"
    ref="formRef"
    label-width="120px"
  >
    <template v-for="item in formSchema" :key="item.prop">
      <el-form-item :label="item.label" :prop="item.prop">
        <!-- 文本输入 -->
        <el-input
          v-if="item.type === 'input'"
          v-model="formData[item.prop]"
          :placeholder="item.placeholder"
          :disabled="submitted"
        />

        <!-- 数字输入 -->
        <el-input-number
          v-else-if="item.type === 'number'"
          v-model="formData[item.prop]"
          :min="item.min"
          :max="item.max"
          :step="item.step"
          :placeholder="item.placeholder"
          :disabled="submitted"
        />

        <!-- 选择框 -->
        <el-select
          v-else-if="item.type === 'select'"
          v-model="formData[item.prop]"
          :placeholder="item.placeholder"
          :disabled="submitted"
        >
          <el-option
            v-for="opt in item.options"
            :key="opt.value"
            :label="opt.label"
            :value="opt.value"
          />
        </el-select>

        <!-- 单选框组 -->
        <el-radio-group
          v-else-if="item.type === 'radio'"
          v-model="formData[item.prop]"
          :disabled="submitted"
        >
          <el-radio
            v-for="opt in item.options"
            :key="opt.value"
            :label="opt.value"
          >
            {{ opt.label }}
          </el-radio>
        </el-radio-group>

        <!-- 取色器 -->
        <el-color-picker
          v-else-if="item.type === 'color'"
          v-model="formData[item.prop]"
          :disabled="submitted"
        />

        <!-- 文件上传 -->
        <el-upload
          v-else-if="item.type === 'file'"
          :action="item.action"
          :on-preview="handlePreview"
          :on-remove="handleRemove"
          :file-list="formData[item.prop]"
          :limit="item.limit"
          :auto-upload="item.autoUpload"
          :disabled="submitted"
        >
          <el-button size="small" type="primary" :disabled="submitted">
            {{ item.uploadButtonText || '点击上传' }}
          </el-button>
          <template #tip>
            <div class="el-upload__tip">{{ item.tip }}</div>
          </template>
        </el-upload>

        <!-- 其他类型 -->
        <div v-else>未知类型：{{ item.type }}</div>
      </el-form-item>
    </template>

    <el-form-item>
      <!-- 提交前显示提交按钮 -->
      <el-button
        type="primary"
        @click="submitForm"
        v-if="!submitted"
      >提交</el-button>

      <!-- 提交后显示更新和下载按钮 -->
      <el-button
        type="success"
        @click="$emit('update', formData)"
        v-if="submitted"
      >更新</el-button>
      <el-button
        type="info"
        @click="$emit('download', formData)"
        v-if="submitted"
      >下载</el-button>
      <el-button @click="resetForm">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { ref, reactive, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

const props = defineProps({
  formSchema: {
    type: Array,
    required: true
  },
  modelValue: {
    type: Object,
    default: () => ({})
  },
  submitted: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['update:modelValue', 'submit', 'update', 'download'])

const formData = reactive({ ...props.modelValue })
const formRef = ref(null)

// 动态生成校验规则
const rules = reactive({})
props.formSchema.forEach(item => {
  if (item.rules) rules[item.prop] = item.rules
})

// 同步 formData 到 v-model
watch(
  formData,
  (newVal) => emit('update:modelValue', { ...newVal }),
  { deep: true }
)

const submitForm = () => {
  formRef.value.validate(valid => {
    if (valid) {
      emit('submit', { ...formData })
      ElMessage.success('提交成功')
    } else {
      ElMessage.error('表单校验失败')
    }
  })
}

const resetForm = () => {
  formRef.value.resetFields()
}

// 文件上传回调示例
const handlePreview = file => ElMessageBox.alert(`预览文件：${file.name}`)
const handleRemove = (file, fileList) => {
  // 根据 prop 更新对应字段
  const prop = fileList.length ? fileList[0]?.name.split('.')[0] : file.name
  formData[prop] = fileList
}
</script>
